home *** CD-ROM | disk | FTP | other *** search
- ; Rewrite-rule compiler (a.k.a. "extend-syntax")
-
- ; To do:
- ; Fix bug with nested ... patterns
- ; Apply rename and compare functions everywhere they should be
-
- ; Example:
- ;
- ; (define-syntax or
- ; (syntax-rules ()
- ; ((or) #f)
- ; ((or e) e)
- ; ((or e1 e ...) (let ((temp e1))
- ; (if temp temp (or e ...))))))
-
- (define (rewrite-syntax-rules exp r c)
- (process-rules (cddr exp) (cadr exp) r c))
-
- (define (process-rules rules subkeywords r c)
- (let ((tail (r 'tail)))
- `(,(r 'lambda) (%input% %rename% %compare%) ;These should be renamed...
- (,(r 'let) ((,tail (,(r 'cdr) %input%)))
- (,(r 'cond) ,@(map (lambda (rule)
- (process-rule rule tail subkeywords r c))
- rules)
- (,(r 'else)
- (syntax-error "use of macro doesn't match definition"
- %input%)))))))
-
- (define (process-rule rule tail subkeywords r c)
- (if (not (= (length rule) 2))
- (syntax-error "ill-formed rule" rule))
- (let ((pattern (car rule))
- (template (cadr rule)))
- (let ((env (process-pattern (cdr pattern) tail null-rank subkeywords)))
- `(,(process-match tail (cdr pattern) subkeywords)
- (,(r 'let*) ,(map (lambda (z)
- `(,(car z) ,(cadr z)))
- env)
- ,(process-template template env null-rank))))))
-
- (define null-rank '())
-
- ; Generate code to test whether input expression matches pattern
-
- (define (process-match input pattern subkeywords)
- (cond ((name? pattern)
- (if (member pattern subkeywords)
- `(%compare% ,input ',pattern)
- `#t))
- ((zero-or-more? pattern)
- (process-list-match input (car pattern) subkeywords))
- ((at-least-one? pattern)
- `(and (not (null? ,input))
- ,(process-list-match input (car pattern) subkeywords)))
- ((pair? pattern)
- `(let ((%temp% ,input))
- (and (pair? %temp%)
- ,(process-match `(car %temp%) (car pattern) subkeywords)
- ,(process-match `(cdr %temp%) (cdr pattern) subkeywords))))
- (else
- `(equal? ,input ',pattern))))
-
- (define (process-list-match input pattern subkeywords)
- `(let loop ((l ,input))
- (or (null? l)
- (and (pair? l)
- ,(process-match '(car l) pattern subkeywords)
- (loop (cdr l))))))
-
- ; Generate code to take apart the input expression
-
- (define (process-pattern pattern path rank subkeywords)
- (cond ((name? pattern)
- (if (name-member pattern subkeywords)
- '()
- (list (list pattern path rank))))
- ((or (zero-or-more? pattern)
- (at-least-one? pattern))
- (let ((temp '%temp%)) ;Bug -- should gensym here!!
- (cons `(,temp ,path)
- (map (lambda (z)
- `(,(car z)
- (map (lambda (%input%)
- ,(cadr z))
- ,temp)
- ,(caddr z)))
- (process-pattern (car pattern)
- '%input%
- (cons (cadr pattern) rank)
- subkeywords)))))
- ((pair? pattern)
- (append (process-pattern (car pattern) `(car ,path) rank subkeywords)
- (process-pattern (cdr pattern) `(cdr ,path) rank subkeywords)))
- (else '())))
-
- ; Generate code to compose the output expression according to template
-
- (define (process-template template env rank)
- (cond ((name? template)
- (let ((probe (name-assoc template env)))
- (if probe
- (if (equal? (caddr probe) rank)
- template
- (syntax-error "syntax-rules: template rank error" template))
- `(%rename% ',template))))
- ((or (zero-or-more? template)
- (at-least-one? template))
- (let ((vars (free-template-vars (car template) env '())))
- (if (null? vars)
- (syntax-error "ill-formed template" template)
- `(map (lambda ,vars
- ,(process-template (car template)
- env
- (cons (cadr template) rank)))
- ,@vars))))
- ((pair? template)
- `(cons ,(process-template (car template) env rank)
- ,(process-template (cdr template) env rank)))
- (else `',template)))
-
- (define (free-template-vars template env free)
- (cond ((name? template)
- (if (and (name-assoc template env)
- (not (name-member template free)))
- (cons template free)
- free))
- ((or (zero-or-more? template)
- (at-least-one? template))
- (free-template-vars (cadr template) env free))
- ((pair? template)
- (free-template-vars (car template) env
- (free-template-vars (cdr template) env free)))
- (else free)))
-
- (define (check-cadr syms)
- (lambda (pattern)
- (and (pair? pattern)
- (pair? (cdr pattern))
- (memq (cadr pattern) syms)
- (or (null? (cddr pattern))
- (syntax-error "segment matching not implemented" pattern)))))
-
- ;(define zero-or-more? (check-cadr `(* ,(string->symbol "..."))))
- ;(define at-least-one? (check-cadr '(+)))
- (define (at-least-one? x) #f)
-
- (define zero-or-more?
- (check-cadr (list (string->symbol "...") '---)))
-